package com.gitee.btssplib

import android.util.Log
import io.reactivex.Observable
import io.reactivex.ObservableOnSubscribe
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers

/**
 * 蓝牙连接心脏，负责心跳，保持连接。
 * @author John
 * @version 1.0
 */
class BTHeart(private val connector: BTConnector, private val innerHeartListener: HeartListener) {

    enum class State {
        IDLE, // 空闲
        BEATING, // 正在心跳
        BEAT_ERROR // 心跳错误
    }

    companion object {
        const val TAG = "BTHeart"
    }

    private var heartbeatThread: Disposable? = null // 心跳线程
    var state: State = State.IDLE // 心脏状态

    @Synchronized
    fun start() {
        Log.d(TAG, "start()")
        when (state) {
            State.IDLE -> {
                beat()
            }
            else -> {
                stop()
                beat()
            }
        }
    }

    private fun beat() {
        heartbeatThread = Observable.create(ObservableOnSubscribe<Int> { observableEmitter ->
            try {
                var beatCount = 0
                while (!observableEmitter.isDisposed) {
                    beatCount++
                    val outputStream = connector.bluetoothSocket?.outputStream
                    outputStream?.write(0)
                    outputStream?.flush()
                    observableEmitter.onNext(beatCount)
                    Log.d(TAG, "心跳正常")
                    Thread.sleep(30000) // 半分钟心跳一次
                }
            } catch (e: Exception) {
                e.printStackTrace()
                observableEmitter.tryOnError(e)
            } finally {
                observableEmitter.onComplete()
            }
        })
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe({ result ->
                    Log.d(TAG, "第${result}次心跳")
                    innerHeartListener?.onBeating(result)
                }, { error ->
                    Log.d(TAG, "心跳发生错误")
                    state = State.BEAT_ERROR
                    error.printStackTrace()
                    innerHeartListener?.onError(error)
                }, {
                    Log.d(TAG, "心跳结束")
                }, {
                    Log.d(TAG, "开始心跳")
                    state = State.BEATING
                    innerHeartListener?.onStart()
                })
    }

    @Synchronized
    fun stop() {
        if (heartbeatThread != null) {
            Log.d(TAG, "正在停止心跳器")
            try {
                heartbeatThread?.dispose()
            } catch (e: Exception) {
                e.printStackTrace()
            } finally {
                heartbeatThread = null
                state = State.IDLE
            }
        }
    }
}